using System;
using System.Collections.Generic;
using Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using TXLooker.Common;
using TXLooker.Common.Core;

namespace TXLooker.Core
{
    internal abstract class OlProviderWrapperBase : SelfUpdater
    {
        public Guid ID
        {
            get { return this.m_id; }
        }
        private Guid m_id = Guid.NewGuid();

        protected OlProviderWrapperBase Parent
        {
            get { return this.m_parent; }
            private set
            {
                this.m_parent = value;
            }
        }
        private OlProviderWrapperBase m_parent = null;

        private OlProviderWrapperBase()
        {
            OlProviderWrapperBase.AddProviderWrapper( this );
        }
        protected OlProviderWrapperBase( OlProviderWrapperBase parent ) : this()
        {
            this.Parent = parent;
        }

        public virtual void Delete()
        {
            OlProviderWrapperBase.RemoveProviderWrapper( this );
            this.Folder.Delete();
        }


        public object SyncFolderObject
        {
            get { return this.m_syncFolderObject; }
        }
        private readonly object m_syncFolderObject = new object();

        public MAPIFolder Folder
        {
            get { return this.m_folder; }
            protected set
            {
                UnBindProviderWrapperByFolder( this.m_folder );
                this.m_folder = value;
                BindProviderWrapperWithFolder( this.m_folder, this );
            }
        }
        private MAPIFolder m_folder = null;

        public abstract void InitFolder( MAPIFolder parentFolder );

        public void InitContextMenu( CommandBar commandBar )
        {
            this.RaiseInitializeContextMenu( commandBar );
        }

        public event TFEventHandler<CommandBar> InitializeContextMenu
        {
            add    { lock( m_syncInitContextMenu ) { this.m_InitializeContextMenuEH += value; } }
            remove { lock( m_syncInitContextMenu ) { this.m_InitializeContextMenuEH -= value; } }
        }
        private TFEventHandler<CommandBar> m_InitializeContextMenuEH = null;
        private readonly object m_syncInitContextMenu = new object();

        private void RaiseInitializeContextMenu(CommandBar contextMenu)
        {
            CommonGlobal.RaiseEventHandler( this.m_InitializeContextMenuEH, new object[] { this, contextMenu }, this.m_syncInitContextMenu );
        }

        public static OlProviderWrapperBase GetProviderWrapper( Guid id )
        {
            OlProviderWrapperBase item = null;

            lock( m_instancesMAP )
            {
                if( m_instancesMAP.ContainsKey(id) )
                    item = m_instancesMAP[id];
            }

            return item;
        }
        private static void AddProviderWrapper(OlProviderWrapperBase item)
        {
            lock( m_instancesMAP )
            {
                if( !m_instancesMAP.ContainsKey( item.ID ) )
                    m_instancesMAP.Add( item.ID, item );
            }
        }
        private static void RemoveProviderWrapper( OlProviderWrapperBase item )
        {
            UnBindProviderWrapperByFolder( item.Folder );

            lock( m_instancesMAP )
            {
                m_instancesMAP.Remove( item.ID );
            }
        }

        //key - OlProviderWrapperBase.ID
        private static Dictionary<Guid, OlProviderWrapperBase> m_instancesMAP = new Dictionary<Guid, OlProviderWrapperBase>();

        public static OlProviderWrapperBase GetProviderWrapperByFolder( MAPIFolder folder )
        {
            OlProviderWrapperBase item = null;

            lock( m_foldersMAP )
            {
                if( m_foldersMAP.ContainsKey( folder.EntryID ) )
                    item = GetProviderWrapper(m_foldersMAP[folder.EntryID]);
            }

            return item;
        }
        public static void BindProviderWrapperWithFolder( MAPIFolder folder, OlProviderWrapperBase provider )
        {
            if( folder == null ) return;

            lock( m_foldersMAP )
            {
                if( m_foldersMAP.ContainsKey(folder.EntryID) )
                {
                    m_foldersMAP[folder.EntryID] = provider.ID;
                }
                else 
                { 
                    m_foldersMAP.Add( folder.EntryID, provider.ID );
                }
            }
        }
        public static void UnBindProviderWrapperByFolder( MAPIFolder folder )
        {
            if( folder == null ) return;

            lock( m_foldersMAP )
            {
                m_foldersMAP.Remove( folder.EntryID );
            }
        }
        //key - folder entry ID
        private static Dictionary<string, Guid> m_foldersMAP = new Dictionary<string, Guid>();

    }
}
